require 'zdc.doc'
require 'zsvc.que'
require 'zsvc.packet'
require 'zsvc.evhandle'
local monutil=require 'zsvc.monutil'
module(..., package.seeall)

local App= {}
zsvc.evhandle.InitEvent(App)
local App_mt = {__metatable = {}, __index = App}


function new(params)
	local obj = setmetatable({name=params.name,mon=params.mon,logger=params.logger,react=params.react,fd=params.fd,app=params.app,que=zsvc.que.new(),sp=zsvc.packet.new(),rp=zsvc.packet.new()}, App_mt)
	obj.authed=false
	monutil.mon_start(obj)
	obj:_bv_init()
	return obj
end

function App:OnClose()
	if self.fd then
		monutil.mon_end(self)
		self:_bv_close()
		self.fd:close()
		self.fd=nil
	end
end

function App:OnMsgSync(packet)
	local h=packet:ParseHeader()
	local por,body=packet:GetMsg()
	local app=self.app
	if app then
		local respone={}
		if self.logger:chkLevel('DEBUG') then
			self.logger:debug('apphandle Sync Req:\n'..zdc.doc.str_print_dbg(body))
		end
		local r,err=xpcall(function () app:HandleRequest(body.ch,body.bd,respone) end,debug.traceback)
		if r then
			if self.logger:chkLevel('DEBUG') then
				self.logger:info('Sync Respone:\n'..zdc.doc.str_print_dbg(respone))
			end
			local np=zsvc.packet.new()
			np:SetMsg(h.appid,body.ch,respone)
			self:SendPacket(np)
		else
			app.dal:ResetCache()
			app.dal:AbortTA()
			local np=zsvc.packet.new()
			np:SetMsg(h.appid,body.ch,{err=err})
			self:SendPacket(np)
			self.logger:error(err)
		end
		return
	end
		
	local np=zsvc.packet.new()
	np:SetMsg(h.appid,body.ch,{err="can't find app"})
	self:SendPacket(np)
	return
end

function App:OnMsgCB(packet)
	local h=packet:ParseHeader()
	local por,body=packet:GetMsg()
	local app=self.app
	if app then
		if self.logger:chkLevel('DEBUG') then
			self.logger:debug('apphandle req:\n'..zdc.doc.str_print_dbg(body))
		end
		local r,err=xpcall(function () app:HandleRequestCB(body.ch,body.bd,function (r,...)
			if not r or r <0 then
				local np=zsvc.packet.new()
				np:SetMsg(h.appid,body.ch,{err=...})
				self:SendPacket(np)
				self.logger:error((...))
			else
				local respone={ret={...}}
				if self.logger:chkLevel('DEBUG') then
					self.logger:info('Respone:\n'..zdc.doc.str_print_dbg(respone))
				end
				local np=zsvc.packet.new()
				np:SetMsg(h.appid,body.ch,respone)
				self:SendPacket(np)
			end
		end) end,debug.traceback)
		if not r then
			app.dal:ResetCache()
			app.dal:AbortTA()
			local np=zsvc.packet.new()
			np:SetMsg(h.appid,body.ch,{err=err})
			self:SendPacket(np)
			self.logger:error(err)
		end
		return
	end
		
	local np=zsvc.packet.new()
	np:SetMsg(h.appid,body.ch,{err="can't find app"})
	self:SendPacket(np)
	return
end
App.OnMsg=App.OnMsgCB
